package ElectricCraft.model;

import ElectricCraft.drawer.Drawer;

import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;

/**
 *
 */
public final class ChipElement {
    public static final int ELEMENT_UNKNOWN     = -1;
	public static final int ELEMENT_WIRE        = 0;
	public static final int ELEMENT_KEY         = 1;
	public static final int ELEMENT_DIODE       = 2;
	public static final int ELEMENT_POWER       = 3;
	public static final int ELEMENT_INPUT       = 4;
	public static final int ELEMENT_OUTPUT      = 5;
	public static final int ELEMENT_MARK        = 6; // inputs & outputs number
	public static final int ELEMENT_CHIP_PART   = 7;

	public int type             = -1;
	public int orientation      = -1;

	// WIRE         - wire type
	// CHIP_PART    - chip part type
	public int itemType         = 0;

	// list of groups that element refers to
	public int [] wireGroups    = null;

    public ChipElement duplicate() {
		ChipElement elem    = new ChipElement();

		assert type != ELEMENT_CHIP_PART;

		elem.type           = type;
		elem.orientation    = orientation;
		elem.itemType       = itemType;

		if (wireGroups != null) {
			elem.wireGroups = new int[wireGroups.length];
			for (int k = 0; k < wireGroups.length; ++k) {
				elem.wireGroups[k] = -1;
			}
		}

		return elem;
	}

	public void initWire() {
		type = ELEMENT_WIRE;

		wireGroups = new int[] { -1, -1 };
		// 1) wire group (west-east)
		// 2) second group (in case of cross) (north-south)

		itemType = Drawer.WIRE_SINGLE;
	}

	public void initKey(boolean state, int orientation) {
		type = ELEMENT_KEY;

		wireGroups = new int[] { -1 };
		// key control group

		this.orientation = orientation;

		itemType = state ? 1 : 0;
	}

	public void initDiode(int orientation) {
		type = ELEMENT_DIODE;

		this.orientation = orientation;
	}

	public void initPower() {
		type = ELEMENT_POWER;
	}

	public void initInput(int index) {
		type = ELEMENT_INPUT;

		itemType = index;
	}

	public void initOutput(int index) {
		type = ELEMENT_OUTPUT;

		itemType = index;
	}

	public void initMarker(int orientation) {
		type = ELEMENT_MARK;

		this.orientation = orientation;
	}

    public void initChip(int chipIndex, int count, int index, boolean isInput) {
        type = ELEMENT_CHIP_PART;

        this.itemType = chipIndex;
        this.orientation = Drawer.getChipOrientation(index, isInput, count);
    }

    public void save(ByteBuffer buffer) throws IOException {
        buffer.putInt(type);
        buffer.putInt(orientation);
        buffer.putInt(itemType);
    }

    public static ChipElement load(InputStream stream, ByteBuffer buffer) throws IOException {
        // type
        int res = stream.read(buffer.array(), 0, 4);
        assert res == 4;

        int type = buffer.getInt(0);
        if (type == ChipElement.ELEMENT_UNKNOWN) {
            return null;
        }

        // orientation & itemType
        res = stream.read(buffer.array(), 0, 8);
        assert res == 8;

        int orientation = buffer.getInt(0);
        int itemType    = buffer.getInt(4);

        ChipElement elem = new ChipElement();
        elem.type           = type;
        elem.orientation    = orientation;
        elem.itemType       = itemType;

        // update wireGroups array
        if (elem.type == ChipElement.ELEMENT_WIRE) {
            elem.wireGroups = new int[] { -1, -1 };
        } else if (elem.type == ChipElement.ELEMENT_KEY) {
            elem.wireGroups = new int[] { -1 };
        }

        return elem;
    }
}
